#ifndef BEMFACLIENT_H
#define BEMFACLIENT_H

#include <QObject>
#include <QTcpSocket>
#include <QTimer>
#include <QJsonObject>
#include <QJsonDocument>
#include <QDateTime>
#include "../core/alarmengine.h"
#include "../core/devicemanager.h"

/**
 * @brief 巴法云TCP客户端类
 *
 * 功能：
 * - 连接巴法云服务器（bemfa.com:8344）
 * - 支持订阅/发布消息（Pub/Sub模式）
 * - 心跳保活机制（每60秒）
 * - 断线自动重连（指数退避策略）
 * - 按配电室分组推送数据（3个主题对应3个配电室）
 * - 汇总数据推送（每60秒）
 * - 报警事件即时推送
 * - 全量数据上传（使用/up后缀，不推送）
 * - 支持APP主动查询
 */
class BemfaClient : public QObject
{
    Q_OBJECT
    Q_PROPERTY(bool connected READ isConnected NOTIFY connectedChanged)
    Q_PROPERTY(QString status READ status NOTIFY statusChanged)
    Q_PROPERTY(int bytesSent READ bytesSent NOTIFY bytesSentChanged)
    Q_PROPERTY(int bytesReceived READ bytesReceived NOTIFY bytesReceivedChanged)

public:
    /**
     * @brief 配电室信息结构
     */
    struct RoomInfo
    {
        int roomId;       ///< 配电室ID（1-3）
        QString roomName; ///< 配电室名称（A、B、C）
        QString topic;    ///< 巴法云主题名称
        int startMeterId; ///< 起始电表ID
        int endMeterId;   ///< 结束电表ID
    };

    explicit BemfaClient(QObject *parent = nullptr);
    ~BemfaClient();

    /**
     * @brief 初始化客户端
     * @param host 服务器地址（默认：bemfa.com）
     * @param port 服务器端口（默认：8344）
     * @param uid 用户私钥
     * @return 是否初始化成功
     */
    bool initialize(const QString &host, int port, const QString &uid);

    /**
     * @brief 设置设备管理器（用于获取电表数据）
     * @param deviceManager 设备管理器指针
     */
    void setDeviceManager(DeviceManager *deviceManager);

    /**
     * @brief 设置报警引擎（用于接收报警事件）
     * @param alarmEngine 报警引擎指针
     */
    void setAlarmEngine(AlarmEngine *alarmEngine);

    /**
     * @brief 添加配电室配置
     * @param roomInfo 配电室信息
     */
    void addRoomConfig(const RoomInfo &roomInfo);

    /**
     * @brief 连接到巴法云服务器
     */
    void connectToServer();

    /**
     * @brief 断开连接
     */
    void disconnectFromServer();

    /**
     * @brief 启动自动推送
     * @param dataPushInterval 汇总数据推送间隔（秒），默认60秒
     * @param fullDataUploadInterval 全量数据上传间隔（秒），默认300秒
     */
    void startAutoPush(int dataPushInterval = 60, int fullDataUploadInterval = 300);

    /**
     * @brief 停止自动推送
     */
    void stopAutoPush();

    /**
     * @brief 订阅主题
     * @param topics 主题列表（逗号分隔）
     * @return 是否发送成功
     */
    bool subscribe(const QString &topics);

    /**
     * @brief 发布消息
     * @param topic 主题名称
     * @param message 消息内容
     * @return 是否发送成功
     */
    bool publish(const QString &topic, const QString &message);

    /**
     * @brief 发布JSON消息
     * @param topic 主题名称
     * @param jsonData JSON对象
     * @return 是否发送成功
     */
    bool publishJson(const QString &topic, const QJsonObject &jsonData);

    /**
     * @brief 手动推送配电室汇总数据
     * @param roomId 配电室ID（1-3），0表示推送所有配电室
     */
    void pushRoomSummary(int roomId = 0);

    /**
     * @brief 手动上传全量数据
     * @param roomId 配电室ID（1-3），0表示上传所有配电室
     */
    void uploadFullData(int roomId = 0);

    /**
     * @brief 是否已连接
     */
    bool isConnected() const { return m_connected; }

    /**
     * @brief 获取连接状态描述
     */
    QString status() const { return m_status; }

    /**
     * @brief 获取已发送字节数
     */
    qint64 bytesSent() const { return m_bytesSent; }

    /**
     * @brief 获取已接收字节数
     */
    qint64 bytesReceived() const { return m_bytesReceived; }

signals:
    /**
     * @brief 连接状态改变信号
     */
    void connectedChanged();

    /**
     * @brief 状态描述改变信号
     */
    void statusChanged();

    /**
     * @brief 已发送字节数改变信号
     */
    void bytesSentChanged();

    /**
     * @brief 已接收字节数改变信号
     */
    void bytesReceivedChanged();

    /**
     * @brief 连接成功信号
     */
    void connectionEstablished();

    /**
     * @brief 连接断开信号
     */
    void connectionLost();

    /**
     * @brief 收到消息信号
     * @param topic 主题名称
     * @param message 消息内容
     */
    void messageReceived(const QString &topic, const QString &message);

    /**
     * @brief 订阅成功信号
     * @param topics 主题列表
     */
    void subscribeSucceeded(const QString &topics);

    /**
     * @brief 发布成功信号
     * @param topic 主题名称
     */
    void publishSucceeded(const QString &topic);

    /**
     * @brief 错误信号
     * @param errorString 错误描述
     */
    void errorOccurred(const QString &errorString);

private slots:
    /**
     * @brief 处理TCP连接成功
     */
    void onConnected();

    /**
     * @brief 处理TCP断开连接
     */
    void onDisconnected();

    /**
     * @brief 处理TCP错误
     */
    void onSocketError(QAbstractSocket::SocketError error);

    /**
     * @brief 处理接收到的数据
     */
    void onReadyRead();

    /**
     * @brief 发送心跳包
     */
    void sendHeartbeat();

    /**
     * @brief 自动推送数据
     */
    void autoPushData();

    /**
     * @brief 自动上传全量数据
     */
    void autoUploadFullData();

    /**
     * @brief 处理报警触发
     * @param event 报警事件
     */
    void onAlarmTriggered(const AlarmEvent &event);

    /**
     * @brief 执行重连
     */
    void performReconnect();

private:
    /**
     * @brief 发送原始命令
     * @param command 命令字符串（必须以\r\n结尾）
     * @return 是否发送成功
     */
    bool sendCommand(const QString &command);

    /**
     * @brief 解析收到的消息
     * @param data 接收到的数据
     */
    void parseReceivedData(const QString &data);

    /**
     * @brief 提取键值对
     * @param data 数据字符串
     * @param key 键名
     * @return 键值，如果不存在返回空字符串
     */
    QString extractValue(const QString &data, const QString &key) const;

    /**
     * @brief 生成配电室汇总数据JSON（精简格式）
     * @param roomId 配电室ID
     * @return JSON对象
     *
     * 精简字段说明（巴法云限制消息长度）：
     * - on: 在线电表数
     * - off: 离线电表数
     * - p: 总功率(kW)
     * - i: 总电流(A)
     * - a: 报警数量
     * - s: 状态(0正常/1报警)
     */
    QJsonObject generateRoomSummary(int roomId);

    /**
     * @brief 生成单个电表的JSON数据
     * @param meter 电表对象
     * @return JSON对象
     */
    QJsonObject generateMeterData(Meter *meter);

    /**
     * @brief 生成报警事件JSON
     * @param event 报警事件
     * @return JSON对象
     */
    QJsonObject generateAlarmData(const AlarmEvent &event);

    /**
     * @brief 获取配电室主题名称
     * @param roomId 配电室ID
     * @return 主题名称
     */
    QString getRoomTopic(int roomId) const;

    /**
     * @brief 根据电表ID获取配电室ID
     * @param meterId 电表ID
     * @return 配电室ID
     */
    int getRoomIdByMeterId(int meterId) const;

    /**
     * @brief 启动重连定时器
     */
    void startReconnectTimer();

    /**
     * @brief 更新状态描述
     * @param status 状态描述
     */
    void setStatus(const QString &status);

    // ========== 配置参数 ==========
    QString m_host;                  ///< 服务器地址
    int m_port;                      ///< 服务器端口
    QString m_uid;                   ///< 用户私钥
    QVector<RoomInfo> m_roomConfigs; ///< 配电室配置列表

    // ========== 网络组件 ==========
    QTcpSocket *m_socket;          ///< TCP套接字
    QTimer *m_heartbeatTimer;      ///< 心跳定时器
    QTimer *m_dataPushTimer;       ///< 数据推送定时器
    QTimer *m_fullDataUploadTimer; ///< 全量数据上传定时器
    QTimer *m_reconnectTimer;      ///< 重连定时器

    // ========== 状态变量 ==========
    bool m_connected;        ///< 是否已连接
    bool m_subscribed;       ///< 是否已订阅
    QString m_status;        ///< 状态描述
    qint64 m_bytesSent;      ///< 已发送字节数
    qint64 m_bytesReceived;  ///< 已接收字节数
    int m_reconnectAttempts; ///< 重连尝试次数
    QString m_receiveBuffer; ///< 接收缓冲区（处理粘包）

    // ========== 协议解析辅助变量 ==========
    QString m_subscribedTopics;   ///< 已订阅的主题列表（用于订阅成功回显）
    QString m_lastPublishedTopic; ///< 最后发布的主题（用于发布成功确认）

    // ========== 业务组件 ==========
    DeviceManager *m_deviceManager; ///< 设备管理器
    AlarmEngine *m_alarmEngine;     ///< 报警引擎
};

#endif // BEMFACLIENT_H
